/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package stud.cp.user.plugins.designer;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.ejb.Stateless;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import stud.cp.core.dbaccess.DAOException;
import stud.cp.core.plugins.PluginConst;
import stud.cp.core.plugins.PluginRouter;
import stud.cp.core.plugins.WrongPageRequest;
import stud.cp.user.dbaccess.*;
import stud.cp.user.valueobjects.*;

/**
 *
 * @author morfant
 */
@Stateless
public class DishesPluginBean implements DishesPluginBeanLocal {

    /**
     * Фабрика DAO классов.
     */
    private OracleDAOFactory oracleDAOFactory = null;
    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("ACPII");

    /**
     * Метод, выполняющий бизнес логику плагина.
     *
     * @param req Реквест.
     * @return Класс плагин.
     */
    @Override
    public PluginRouter perform(HttpServletRequest req) {
        String subaction = req.getParameter(PluginConst.SUBACTION);


        if ((subaction != null) && (!subaction.equals(""))) {
            try {

                oracleDAOFactory = new OracleDAOFactory();
                oracleDAOFactory.initialize();
                /*
                 * Список действий которые могут выполниться.
                 */

                if (subaction.equals(PluginConst.GET_LIST)) {
                    return getListOfDishes(req);
                }

                /*
                 * Страница добавления
                 */
                if (subaction.equals(PluginConst.GET_ADD_PAGE)) {
                    return getAddPage(req);
                }

                /*
                 * Добавление новых данных
                 */
                if (subaction.equals(PluginConst.NEW_DATA)) {
                    return newData(req);
                }

                /*
                 * Страница редактирования
                 */
                if (subaction.equals(PluginConst.GET_EDIT_PAGE)) {
                    return getEditPage(req);
                }

                /*
                 * Сохранение измененных данных
                 */
                if (subaction.equals(PluginConst.SAVE_DATA)) {
                    return saveData(req);
                }

                /*
                 * Страница удаления
                 */
                if (subaction.equals(PluginConst.GET_DELETE_PAGE)) {
                    return getDeletePage(req);
                }

                /*
                 * Удаление данные
                 */
                if (subaction.equals(PluginConst.DELETE_DATA)) {
                    return deleteData(req);
                }

                if (subaction.equals(PluginConst.TEMPORARY_DELETE)) {
                    return temporaryDeleteData(req);
                }

                /*
                 * Страница просмотра данных о типе оружия
                 */
                if (subaction.equals(PluginConst.GET_VIEW_PAGE)) {
                    return getViewPage(req);
                }

                //                /*Страница со списком свойств, принадлежащий данному типу оружия.*/
                //                if (subaction.equals(PluginConst.GET_WEAPON_TYPE_PROPERTIES_LIST)) {
                //                    return getObjectTypePropertyListPage(req);
                //                }
                //
                //                /*Страница с диалогом для пользователя, который хочет исключить свойство из типа оружия.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE_PAGE)) {
                //                    return getExcludePropertyFromObjectTypePage(req);
                //                }
                //
                //                /*Исключение свойства из объектного типа.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE)) {
                //                    return excludePropertyFromObjectType(req);
                //                }
                //
                //                /*Страница добавления свойств к типу оружия.*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE_PAGE)) {
                //                    return getAddPropertiesToObjectTypePage(req);
                //                }
                //
                //                /*Добавление свойств к объектному типу*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE)) {
                //                    return addPropertiesToObjectType(req);
                //                }

                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Действия для данного типа поддействия не найдено. Тип поддействия = " + subaction);
            } catch (DAOException ex) {
                logger.debug("Error due access to database. "
                        + "Plugin = ProductTypesPluginBean. "
                        + "Subaction=" + subaction, ex);
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Ошибка доступа к базе данных " + ex.getMessage());
            } catch (WrongPageRequest ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Данные из реквеста ошибочны :\n" + ex.getMessage());
            } catch (NumberFormatException ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "ID объекта не имеет числовой формат :\n" + ex.getMessage());
            } finally {

                if (oracleDAOFactory != null) {
                    try {
                        oracleDAOFactory.cleanUp();
                    } catch (DAOException ex) {
                        logger.debug("Error due access to database. "
                                + "Plugin = ProductTypesPluginBean. "
                                + "Subaction=" + subaction, ex);
                        req.setAttribute(PluginConst.ERROR_MESSAGE,
                                "Ошибка доступа к базе данных " + ex.getMessage());
                    }
                }
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE,
                    "Тип поддействия не задан.");
        }

        return new PluginRouter("/errorpage.jsp");
    }

    private PluginRouter getListOfDishes(HttpServletRequest req) throws DAOException, WrongPageRequest {

        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);
        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {

            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);

            List<DBObject> listOfDBObject =
                    oracleDAOFactory.getObjectDAO().getAllObjectByObjectTypeButNotDelete(objectTypeId);
            req.setAttribute(PluginConst.OBJECT_LIST, listOfDBObject);

            return new PluginRouter("/Designer/Dishes/DishesTable.jsp");
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectTypeId + " не существует. ");
        }

    }

    private PluginRouter getAddPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        //Получаем объектный тип блюда.
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);
        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);

        if (objectType != null) {
            //Сохраняем объектный тип блюда в реквест.
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);

            List<DBObjectType> productTypeList =
                    oracleDAOFactory.getObjectTypesDAO().getObjectTypeHeirsButNotDelete(PluginConst.PRODUCTS_OBJECT_TYPE_ID);

            //Сохраняем на страницу список типов продуктов.
            req.setAttribute(PRODUCT_OBJECT_TYPE_LIST, productTypeList);

            List<DBObject> productList;
            List<Parameter> productParameterList;
            BigInteger productObjectTypeId;

            ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
            ParametersDAO paramDAO = oracleDAOFactory.getParameterDAO();
            //Для каждого типа продукта добавляем в реквест список продуктов этого типа и параметры этих продуктов.
            for (DBObjectType productObjectType : productTypeList) {
                productObjectTypeId = productObjectType.getObject_type_id();
                productList = objectDAO.getAllObjectByObjectTypeButNotDelete(productObjectTypeId);
                //Добавляем для типа продукта список продуктов.
                req.setAttribute(productObjectTypeId.toString(), productList);
                for (DBObject product : productList) {
                    //Для каждого продукта добавляем список его параметров.
                    productParameterList = paramDAO.getPropertyValueForObject(product.getObject_id());
                    req.setAttribute(PRODUCT_PARAMETER_LIST_FOR_PRODUCT + "=" + product.getObject_id().toString(), productParameterList);
                }
            }
            return new PluginRouter("/Designer/Dishes/AddDish.jsp");
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectTypeId + " не существует. ");
        }
    }
    private static final String PRODUCT_XML_ROOT_ELEMENT = "PRODUCT_XML_ROOT_ELEMENT";
    private static final String PRODUCT_XML_PRODUCT_ELEMENT = "PRODUCT_XML_PRODUCT_ELEMENT";
    private static final String PRODUCT_XML_PRODUCT_ID_ATTRIBUTE = "PRODUCT_XML_PRODUCT_ID_ATTRIBUTE";
    private static final String PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE = "PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE";

    /**
     * Метод, позволяющий добавлять новые данные.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter newData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        //Получаем объектный тип блюда.
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);
        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);

        String name = req.getParameter(PluginConst.OBJECT_NAME);
        String description = req.getParameter(PluginConst.OBJECT_DESCRIPTION);
        String dishCost = req.getParameter(PluginConst.DISH_COST);
        String primeDishCost = req.getParameter(PluginConst.PRIME_DISH_COST);

        String[] productIds = req.getParameterValues(DISH_PRODUCT_IDS);
        int productNumber = productIds.length;

        Document document = new Document();
        Element rootElement = new Element(PRODUCT_XML_ROOT_ELEMENT);
        String productCost;
        Element productElement;
        if (objectType != null) {
            BigInteger object_id =
                    oracleDAOFactory.getObjectDAO().
                    create(new DBObject(objectType.getObject_type_id(), name, description));

            ObjectReferencesDAO objectReferencesDAO = oracleDAOFactory.getObjectReferencesDAO();

            for (int i = 0; i < productNumber; i++) {
                productCost = req.getParameter(PluginConst.AMOUNT + productIds[i]);
                productElement = new Element(PRODUCT_XML_PRODUCT_ELEMENT);
                productElement.setAttribute(PRODUCT_XML_PRODUCT_ID_ATTRIBUTE, productIds[i]);
                productElement.setAttribute(PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE, productCost);
                rootElement.addContent(productElement);
                objectReferencesDAO.create(
                        new DBObjectReference(object_id,
                        new BigInteger(productIds[i]),
                        PluginConst.LINK_ON_PRODUCT_PRODPERTY_ID));
            }

            document.setContent(rootElement);

            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            String recipeXMLString = outputter.outputString(document);


            ParametersDAO propertyValueDAO = oracleDAOFactory.getParameterDAO();

            propertyValueDAO.create(new Parameter(PluginConst.DIST_COST_PROPERTY_ID, dishCost, object_id, null));
            propertyValueDAO.create(new Parameter(PluginConst.RECIPE_PROPERTY_ID, recipeXMLString, object_id, null));
            propertyValueDAO.create(new Parameter(PluginConst.DISH_PRIME_COST_PROPERTY_ID, primeDishCost, object_id, null));


            //TODO::[High] добавить код, которые переносит данные в историю.
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectTypeId + " не существует. ");
        }


        return new PluginRouter("dishes-action.do"
                + "?"
                + PluginConst.SUBACTION
                + "="
                + PluginConst.GET_LIST
                + "&"
                + PluginConst.OBJECT_TYPE_ID
                + "="
                + objectTypeId, false);
    }

    /**
     * Метод, который позволяет перейти на страницу удаления элемента.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getDeletePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objecеIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objecеIdValue == null) || (objecеIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objecеId =
                new BigInteger(objecеIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objecеId);
        if (object != null) {
            req.setAttribute(PluginConst.OBJECT, object);


            List<DBObjectReference> listOfReferenceFromOrders =
                    oracleDAOFactory.getObjectReferencesDAO().
                    getRefenceOfInProgressOrderToCurrentDish(objecеId);


            String errorMessage = "";
            if (listOfReferenceFromOrders.size() != 0) {

                ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
                errorMessage += "Не возможно произвести удаление.";
                errorMessage += "Данное блюдо входит в исполняемые заказы : <br/>";
                for (DBObjectReference orderReference : listOfReferenceFromOrders) {
                    errorMessage += (objectDAO.getById(orderReference.getObject_id()).getName() + "<br/>");
                }
            }

            if (!errorMessage.equals("")) {
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
            }

            return new PluginRouter("/Designer/Dishes/DeleteDish.jsp");
        } else {
            throw new WrongPageRequest("Блюад с таким id=" + objecеId + " не существует. ");
        }

    }

    /**
     * Метод, удаляющий данные из базы данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter deleteData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);

        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);
        if (object != null) {
            oracleDAOFactory.getObjectDAO().delete(object.getObject_id());
            return new PluginRouter("dishes-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST
                    + "&"
                    + PluginConst.OBJECT_TYPE_ID
                    + "="
                    + object.getObject_type_id(), false);
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectId + " не существует. ");
        }

    }

    /**
     * Метод, который позволяет перейти на страницу редактирования данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getEditPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        //Получаем id блюда.
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {
            //Сохраняем объектный тип блюда в реквест.
            req.setAttribute(PluginConst.OBJECT, object);

            req.setAttribute(PluginConst.OBJECT_TYPE, oracleDAOFactory.getObjectTypesDAO().getById(object.getObject_type_id()));

            List<DBObjectType> productTypeList =
                    oracleDAOFactory.getObjectTypesDAO().getObjectTypeHeirsButNotDelete(PluginConst.PRODUCTS_OBJECT_TYPE_ID);

            //Сохраняем на страницу список типов продуктов.
            req.setAttribute(PRODUCT_OBJECT_TYPE_LIST, productTypeList);

            List<DBObject> productList;
            List<Parameter> productParameterList;
            BigInteger productObjectTypeId;

            ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
            ParametersDAO paramDAO = oracleDAOFactory.getParameterDAO();
            //Для каждого типа продукта добавляем в реквест список продуктов этого типа и параметры этих продуктов.
            for (DBObjectType productObjectType : productTypeList) {
                productObjectTypeId = productObjectType.getObject_type_id();
                productList = objectDAO.getAllObjectByObjectTypeButNotDelete(productObjectTypeId);
                //Добавляем для типа продукта список продуктов.
                req.setAttribute(productObjectTypeId.toString(), productList);
                for (DBObject product : productList) {
                    //Для каждого продукта добавляем список его параметров.
                    productParameterList = paramDAO.getPropertyValueForObject(product.getObject_id());
                    req.setAttribute(PRODUCT_PARAMETER_LIST_FOR_PRODUCT + "=" + product.getObject_id().toString(), productParameterList);
                }
            }

            //Сбор данных для отображения положения дел для данного блюда.
            //Работаем с параметрами объекта - блюда.
            List<Parameter> parameterList = oracleDAOFactory.getParameterDAO().getPropertyValueForObject(objectId);

            for (Parameter param : parameterList) {
                if (param.getProperty_id().equals(PluginConst.DIST_COST_PROPERTY_ID)) {
                    //Если это цена в меню блюда - записываем её в реквест.
                    req.setAttribute(PluginConst.DISH_COST, param);
                }
                if (param.getProperty_id().equals(PluginConst.DISH_PRIME_COST_PROPERTY_ID)) {
                    //Если это цена в меню блюда - записываем её в реквест.
                    req.setAttribute(PluginConst.PRIME_DISH_COST, param);
                }
                if (param.getProperty_id().equals(PluginConst.RECIPE_PROPERTY_ID)) {
                    //Если это рецепт, то работаем с рецептом.
                    String recipeXML = param.getValue();
                    SAXBuilder builder = new SAXBuilder();
                    try {
                        //Разбираем рецепт.
                        //Парсим отношение продуктов и их количества из xml.
                        Document document = builder.build(new ByteArrayInputStream(recipeXML.getBytes()));
                        Element root = document.getRootElement();
                        List<Element> productElementList = root.getChildren(PRODUCT_XML_PRODUCT_ELEMENT);

                        Map<BigInteger, String> productAmount = new HashMap<BigInteger, String>();
                        BigInteger productId;
                        for (Element productElement : productElementList) {
                            productId = new BigInteger(
                                    productElement.getAttributeValue(PRODUCT_XML_PRODUCT_ID_ATTRIBUTE));

                            productAmount.put(productId, productElement.getAttributeValue(PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE));
                        }

                        req.setAttribute(PluginConst.PRODUCT_AMOUNT_MAP, productAmount);


                        ObjectReferencesDAO objectReferencesDAO = oracleDAOFactory.getObjectReferencesDAO();

                        List<DBObjectReference> objectReferencesList = objectReferencesDAO.getAllReferenceForObject(objectId);

                        req.setAttribute(PluginConst.RECIPE_PRODUCT_LINK_LIST, objectReferencesList);


                    } catch (JDOMException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    } catch (IOException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    }
                }
            }


            List<DBObjectReference> listOfReferenceFromOrders =
                    oracleDAOFactory.getObjectReferencesDAO().
                    getRefenceOfInProgressOrderToCurrentDish(objectId);


            String errorMessage = "";
            if (listOfReferenceFromOrders.size() != 0) {
                errorMessage += "Не возможно произвести редактирование.";

                errorMessage += "Данное блюдо входит в исполняемые заказы : <br/>";
                for (DBObjectReference orderReference : listOfReferenceFromOrders) {
                    errorMessage += (objectDAO.getById(orderReference.getObject_id()).getName() + "<br/>");
                }
            }

            if (!errorMessage.equals("")) {
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
            }

            return new PluginRouter("/Designer/Dishes/EditDish.jsp");
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectId + " не существует. ");
        }

    }

    private int findReferenceIdInListOfReference(List<DBObjectReference> referenceList, BigInteger referenceId) {

        int i = 0;
        int size = referenceList.size();
        boolean isFound = false;

        DBObjectReference reference;

        while ((!isFound) && (i < size)) {
            reference = referenceList.get(i);
            if (reference.getReference_object_id().equals(referenceId)) {
                isFound = true;
            } else {
                i++;
            }
        }

        if (isFound) {
            return i;
        } else {
            return -1;
        }
    }

    /**
     * Сохранение данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter saveData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        //Получаем объектный тип блюда.
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        String name = req.getParameter(PluginConst.OBJECT_NAME);
        String description = req.getParameter(PluginConst.OBJECT_DESCRIPTION);
        String dishCost = req.getParameter(PluginConst.DISH_COST);
        String dishPrimeCost = req.getParameter(PluginConst.PRIME_DISH_COST);

        String[] productIds = req.getParameterValues(DISH_PRODUCT_IDS);
        int productNumber = productIds.length;

        Document document = new Document();
        Element rootElement = new Element(PRODUCT_XML_ROOT_ELEMENT);
        String productCost;
        Element productElement;
        if (object != null) {

            object.setName(name);
            object.setDescription(description);

            oracleDAOFactory.getObjectDAO().update(object);

            ObjectReferencesDAO objectReferencesDAO = oracleDAOFactory.getObjectReferencesDAO();

            List<DBObjectReference> oldBObjectReferenceList = objectReferencesDAO.getAllReferenceForObject(objectId);

            int position;
            BigInteger productId;

            for (int i = 0; i < productNumber; i++) {
                productCost = req.getParameter(PluginConst.AMOUNT + productIds[i]);
                productElement = new Element(PRODUCT_XML_PRODUCT_ELEMENT);
                productElement.setAttribute(PRODUCT_XML_PRODUCT_ID_ATTRIBUTE, productIds[i]);
                productElement.setAttribute(PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE, productCost);
                rootElement.addContent(productElement);

                productId = new BigInteger(productIds[i]);
                position = findReferenceIdInListOfReference(oldBObjectReferenceList, new BigInteger(productIds[i]));

                //Обрабатываем ссылки на продукты. (Которые уже существуют.)
                if (position != -1) {
                    oldBObjectReferenceList.remove(position);
                } else {
                    objectReferencesDAO.create(
                            new DBObjectReference(objectId,
                            new BigInteger(productIds[i]),
                            PluginConst.LINK_ON_PRODUCT_PRODPERTY_ID));
                }
            }

            //Удаляем не нужные ссылки на продукты.
            for (DBObjectReference obsoletReference : oldBObjectReferenceList) {
                objectReferencesDAO.delete(obsoletReference.getObject_reference_id());
            }

            document.setContent(rootElement);

            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            String recipeXMLString = outputter.outputString(document);

            ParametersDAO propertyValueDAO = oracleDAOFactory.getParameterDAO();

            List<Parameter> parameterList = propertyValueDAO.getPropertyValueForObject(objectId);

            for (Parameter parameter : parameterList) {
                if (parameter.getProperty_id().equals(PluginConst.DIST_COST_PROPERTY_ID)) {
                    parameter.setValue(dishCost);
                    propertyValueDAO.update(parameter);
                }
                if (parameter.getProperty_id().equals(PluginConst.RECIPE_PROPERTY_ID)) {
                    parameter.setValue(recipeXMLString);
                    propertyValueDAO.update(parameter);
                }
                if (parameter.getProperty_id().equals(PluginConst.DISH_PRIME_COST_PROPERTY_ID)) {
                    parameter.setValue(dishPrimeCost);
                    propertyValueDAO.update(parameter);
                }
            }


            //TODO::[High] добавить код, которые переносит данные в историю.
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectId + " не существует. ");
        }


        return new PluginRouter("dishes-action.do"
                + "?"
                + PluginConst.SUBACTION
                + "="
                + PluginConst.GET_VIEW_PAGE
                + "&"
                + PluginConst.OBJECT_ID
                + "="
                + object.getObject_id(), false);

    }

    private PluginRouter getViewPage(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {
            //Записали объектный тип в реквест.
            DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(object.getObject_type_id());
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);
            //Записали объект в реквест.
            req.setAttribute(PluginConst.OBJECT, object);
            //Работаем с параметрами объекта - блюда.
            List<Parameter> parameterList = oracleDAOFactory.getParameterDAO().getPropertyValueForObject(objectId);

            for (Parameter param : parameterList) {
                if (param.getProperty_id().equals(PluginConst.DIST_COST_PROPERTY_ID)) {
                    //Если это цена в меню блюда - записываем её в реквест.
                    req.setAttribute(PluginConst.DISH_COST, param);
                }
                if (param.getProperty_id().equals(PluginConst.DISH_PRIME_COST_PROPERTY_ID)) {
                    //Если это цена в меню блюда - записываем её в реквест.
                    req.setAttribute(PluginConst.PRIME_DISH_COST, param);
                }
                if (param.getProperty_id().equals(PluginConst.RECIPE_PROPERTY_ID)) {
                    //Если это рецепт, то работаем с рецептом.
                    String recipeXML = param.getValue();
                    SAXBuilder builder = new SAXBuilder();
                    try {
                        //Разбираем рецепт.
                        //Парсим отношение продуктов и их количества из xml.
                        Document document = builder.build(new ByteArrayInputStream(recipeXML.getBytes()));
                        Element root = document.getRootElement();
                        List<Element> productElementList = root.getChildren(PRODUCT_XML_PRODUCT_ELEMENT);

                        Map<BigInteger, String> productAmount = new HashMap<BigInteger, String>();
                        BigInteger productId;
                        for (Element productElement : productElementList) {
                            productId = new BigInteger(
                                    productElement.getAttributeValue(PRODUCT_XML_PRODUCT_ID_ATTRIBUTE));

                            productAmount.put(productId, productElement.getAttributeValue(PRODUCT_XML_PRODUCT_AMOUNT_ATTRIBUTE));
                        }

                        //Собираем ссылки на продукты.
                        List<DBObject> productList = new LinkedList<DBObject>();

                        ObjectReferencesDAO objectReferencesDAO = oracleDAOFactory.getObjectReferencesDAO();
                        ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();

                        List<DBObjectReference> objectReferencesList = objectReferencesDAO.getAllReferenceForObject(objectId);

                        for (DBObjectReference objectReference : objectReferencesList) {
                            productList.add(objectDAO.getById(objectReference.getReference_object_id()));
                        }

                        //Поднимаем объектные типы - типы продуктов для создания иерархии.
                        List<DBObjectType> productTypeList = new LinkedList<DBObjectType>();

                        Map<BigInteger, List<DBObject>> productTypeProductsMap = new HashMap<BigInteger, List<DBObject>>();

                        BigInteger productTypeID;
                        List<DBObject> productForProductTypeList;

                        ObjectTypesDAO objectTypesDAO = oracleDAOFactory.getObjectTypesDAO();

                        for (DBObject product : productList) {
                            productTypeID = product.getObject_type_id();

                            if (productTypeProductsMap.containsKey(productTypeID)) {
                                productForProductTypeList = productTypeProductsMap.get(productTypeID);
                                productForProductTypeList.add(product);
                            } else {
                                productTypeList.add(objectTypesDAO.getById(productTypeID));
                                productForProductTypeList = new LinkedList<DBObject>();
                                productForProductTypeList.add(product);
                                productTypeProductsMap.put(productTypeID, productForProductTypeList);
                            }
                        }


                        //Сохраняем на страницу список типов продуктов.
                        req.setAttribute(PRODUCT_OBJECT_TYPE_LIST, productTypeList);

                        List<Parameter> productParameterList;
                        BigInteger productObjectTypeId;

                        ParametersDAO paramDAO = oracleDAOFactory.getParameterDAO();


                        //Для каждого типа продукта добавляем в реквест список продуктов этого типа и параметры этих продуктов.
                        for (DBObjectType productObjectType : productTypeList) {
                            productObjectTypeId = productObjectType.getObject_type_id();
                            productList = productTypeProductsMap.get(productObjectTypeId);
                            //Добавляем для типа продукта список продуктов.
                            req.setAttribute(productObjectTypeId.toString(), productList);
                            for (DBObject product : productList) {
                                //Для каждого продукта добавляем список его параметров.
                                productParameterList = paramDAO.getPropertyValueForObject(product.getObject_id());

                                productParameterList.add(
                                        new Parameter(
                                        null, PluginConst.RECIPE_PROPERTY_ID,
                                        productAmount.get(product.getObject_id()),
                                        null, null, null, objectIdValue, null, null));
                                req.setAttribute(PRODUCT_PARAMETER_LIST_FOR_PRODUCT
                                        + "="
                                        + product.getObject_id().toString(), productParameterList);
                            }
                        }

                        //                    req.setAttribute(PluginConst.STORE_TYPE_PARAMETER, param);
                    } catch (JDOMException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    } catch (IOException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    } catch (Exception ex) {
                        logger.debug(ex);
                    }
                }
            }

            return new PluginRouter("/Designer/Dishes/ViewDish.jsp");
        } else {
            throw new WrongPageRequest("Блюдо с таким id=" + objectId + " не существует. ");
        }
    }

    private Parameter foundCostProductParameter(List<Parameter> listOfParameter) {

        int i = 0;
        int size = listOfParameter.size();
        boolean isFound = false;
        Parameter param = null;

        while ((!isFound) && (i < size)) {
            param = listOfParameter.get(i);
            if (param.getProperty_id().equals(PluginConst.COST_PROPERTY_ID)) {
                isFound = true;
            } else {
                i++;
            }
        }

        return param;
    }

    private PluginRouter temporaryDeleteData(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);

        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);
        if (object != null) {
//            oracleDAOFactory.getObjectDAO().delete(object.getObject_id());
            object.setIsDelete(Boolean.TRUE);
            object.setName("[Удалено]" + object.getName());
            oracleDAOFactory.getObjectDAO().update(object);
            return new PluginRouter("dishes-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST
                    + "&"
                    + PluginConst.OBJECT_TYPE_ID
                    + "="
                    + object.getObject_type_id(), false);
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectId + " не существует. ");
        }
    }
}
